//Header files
#include <stdio.h>
#include <string.h>
#include <spu_mfcio.h>
#include "common.h"

CONTROL_BLOCK cb QWORD_ALIGNED;
char *originalPicture QWORD_ALIGNED;
char *changedPicture QWORD_ALIGNED;

// Set this to 1 to print out debug information on data transfers
#define DEBUG_MFC 0

void j_mfc_get(volatile void *ls, ea_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid)
{
	// A wrapper for mfc_get which checks its parameters and optionally prints out debug information
	printf("get %p %p %d\n", ls, (void *)ea, size);

	if ((size > 16) &&
			(((uint32_t)ls & 0xF) ||
					(ea & 0xF) ||
					(ea == 0) ||
					(size > 16384)))
	{
		printf("j_mfc_get error (ls=%p, ea = %llx, size = %d)\n", ls, ea, size);
	}
	mfc_get(ls, ea, size, tag, tid, rid);
}

void j_mfc_put(volatile void *ls, ea_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid)
{
	// A wrapper for mfc_put which checks its parameters and optionally prints out debug information
	printf("put %p %p %d\n", ls, (void *)ea, size);
	if (((uint32_t)ls & 0xF) ||
			(ea & 0xF) ||
			(ea == 0) ||
			(size > 16384))
	{
		printf("j_mfc_put error (ls=%p, ea = %llx, size = %d)\n", ls, ea, size);
	}
	mfc_put(ls, ea, size, tag, tid, rid);
}

void j_large_mfc_get(volatile void *ls, ea_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid)
{
	// The largest size that mfc_get can deal with is 2^14.
	// For anything larger than this, we need to break it down into chunks
	while (size)
	{
		uint32_t thisSize = MIN(size, 16384);
		j_mfc_get(ls, ea, thisSize, tag, tid, rid);
		size -= thisSize;
		ls = (void *)((char *)ls + thisSize);
		ea += thisSize;
	}
}

int main(uint64_t speid,uint64_t argp, uint64_t envp)
{
	int i;
	CONTROL_BLOCK cb QWORD_ALIGNED;
	PIXEL changedPixels[MAX_PIXELS] QWORD_ALIGNED; //Holds the changed picture
	PIXEL * originalPixels = (PIXEL *)memalign(16, (((MAX_PIXELS * 3)%16 + 1) * 16));

	// Get the control block from the ppu via DMA
	j_mfc_get(&cb, argp, sizeof(CONTROL_BLOCK), 0, 0, 0);
	mfc_write_tag_mask(1 << 0);
	mfc_read_tag_status_all();

	int j;
		   for (j = 0; j < MAX_PIXELS; j++)
		   {
			   originalPixels[0].red = 7;
			   originalPixels[0].red = 7;
			   originalPixels[0].red = 7;
		   }

	//get custom value
	j_mfc_get(&originalPixels[0], cb.originalPixels, (((MAX_PIXELS * 3)%16 + 1) * 16),0,0,0);
	mfc_write_tag_mask(1 << 0);
	mfc_read_tag_status_all();

	if (0)
	{
	   for (j = 0; j < MAX_PIXELS; j++)
	   {
		   printf ("Pixel: %d", j);
		   printf("************%d \n", originalPixels[j].red);
		   printf("************%d \n", originalPixels[j].blue);
		   printf("************%d \n", originalPixels[j].green);
	   }
	}

	// Manipulate the picture
	for (i = 0; i < MAX_PIXELS; i++)
	{
		//changedPixels[i] =  originalPixels[i]; //Just do a 1:1 mapping for now.
		changedPixels[i].red = originalPixels[i].green;
		changedPixels[i].blue = originalPixels[i].blue;
		changedPixels[i].green = originalPixels[i].red;
	}




  return 0;  
}
